﻿using System;
using System.Linq;
using Colligate;

namespace OrgDataSource
{
// ReSharper disable InconsistentNaming
    public class AuthenticationDS:IOrgDS
// ReSharper restore InconsistentNaming
    {
        #region\\delete
        public int DeleteTaskData(OUDataInfo userInfo, string dataGuid, string dataType, orgEntities context)
        {
            switch (dataType.ToLower())
            {
                case "account": return DeleteAccount(dataGuid, context);
                case "certification": return DeleteCertification(dataGuid, context);
                default: throw new Exception("AuthenticationDS无法处理该" + dataType + "的数据");
            }
        }

        private static int DeleteAccount(string dataGuid, orgEntities context)
        {
            try
            {
                var account = context.Account.FirstOrDefault(cc => cc.Guid == dataGuid);
                context.DeleteObject(account);
                var result = context.SaveChanges();
                return result == 1 ? 0 : 1;
            }
            catch
            {
                throw new Exception("删除数据标识为：" + dataGuid + "的Account数据时出错！");
            }

        }
        private static int DeleteCertification(string dataGuid, orgEntities context)
        {
            try
            {
                var certification = context.Certificate.FirstOrDefault(cc => cc.Guid == dataGuid);
                context.DeleteObject(certification);
                var result = context.SaveChanges();
                return result == 1 ? 0 : 1;
            }
            catch
            {
                throw new Exception("删除数据标识为：" + dataGuid + "的Certification数据时出错！");
            }

        }
        #endregion
        #region\\get
        public System.Xml.XmlNode GetTaskData(OUDataInfo userInfo, string dataGuid, string dataType, orgEntities context, BaseTaskDataSource baseInfo)
        {
           switch (dataType.ToLower())
            {
                case "account": return GetAccount(dataGuid, context);
                case "certificate": return GetCertificate(dataGuid, context);
                default: throw new Exception("AuthenticationDS无法处理该" + dataType + "的数据");
            }
        }

        private static System.Xml.XmlNode GetAccount(string dataGuid, orgEntities context)
        {
            try
            {
                var result = XmlNodeManage.GetDocumentNode(Utility.GetTaskGuid(), dataGuid, "Account");
                var account = context.Account.FirstOrDefault(cc => cc.Guid == dataGuid) ?? new Account
                                                                                               {
                                                                                                   Guid = string.Empty,
                                                                                                   AccountName = string.Empty,
                                                                                                   Password = string.Empty,
                                                                                                   Type = string.Empty,
                                                                                                   Name = string.Empty,
                                                                                                   Status = string.Empty,
                                                                                                   IsEvection=string.Empty
                                                                                              
                                                                                               };
                XmlNodeManage.SetSubValue(result, "Guid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), account.Guid);
                XmlNodeManage.SetSubValue(result, "AccountName", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), account.AccountName);
                XmlNodeManage.SetSubValue(result, "Password", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), account.Password);
                XmlNodeManage.SetSubValue(result, "Type", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), account.Type);
                XmlNodeManage.SetSubValue(result, "Name", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), account.Name);
                XmlNodeManage.SetSubValue(result, "Status", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), account.Status);
                XmlNodeManage.SetSubValue(result, "IsEvection", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), account.IsEvection);
                return result;
            }
            catch
            {
                throw new Exception("获取数据标识为：" + dataGuid + "的Account数据时出错！");
            }
        }
        private static System.Xml.XmlNode GetCertificate(string dataGuid, orgEntities context)
        {
            try
            {
                var result = XmlNodeManage.GetDocumentNode(Utility.GetTaskGuid(), dataGuid, "Certificate");
                var certificate = context.Certificate.FirstOrDefault(cc => cc.Guid == dataGuid) ?? new Certificate
                                                                                                       {
                                                                                                           Guid = string.Empty,
                                                                                                           AccountName = string.Empty,
                                                                                                           PublicKey = string.Empty,
                                                                                                           Type = string.Empty,
                                                                                                           Name = string.Empty,
                                                                                                           Status = string.Empty
                                                                                                       };
                XmlNodeManage.SetSubValue(result, "Guid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), certificate.Guid);
                XmlNodeManage.SetSubValue(result, "AccountName", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), certificate.AccountName);
                XmlNodeManage.SetSubValue(result, "PublicKey", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), certificate.PublicKey);
                XmlNodeManage.SetSubValue(result, "Type", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), certificate.Type);
                XmlNodeManage.SetSubValue(result, "Name", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), certificate.Name);
                XmlNodeManage.SetSubValue(result, "Status", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), certificate.Status);
                return result;
            }
            catch
            {
                throw new Exception("获取数据标识为：" + dataGuid + "的Certificate数据时出错！");
            }
        }
        #endregion
        #region\\set
        public int SetTaskData(OUDataInfo userInfo, string dataGuid, string dataType, System.Xml.XmlNode xmlData, orgEntities context)
        {
            var datatype = XmlNodeManage.GetSubValue(xmlData, "@DataType");
            switch (datatype.ToLower())
            {
                case "account": return SetAccount(xmlData, context);
                case "certificate": return SetCertificate(xmlData, context);
                default: throw new Exception("AuthenticationDS无法处理该" + datatype + "的数据");
            }
        }

        private static int SetAccount(System.Xml.XmlNode xmlData, orgEntities context)
        {
            try
            {
                var id =Utility.CheckXmlData(xmlData,"Guid");
                var account = context.Account.FirstOrDefault(cc => cc.Guid == id);
                if (null == account)
                {
                    account = new Account
                                  {
                                      Guid = id,
                                      AccountName = Utility.CheckXmlData(xmlData, "AccountName"),
                                      Password = Utility.CheckXmlData(xmlData, "Password"),
                                      Type = Utility.CheckXmlData(xmlData, "Type"),
                                      Name = Utility.CheckXmlData(xmlData, "Name"),
                                      Status = Utility.CheckXmlData(xmlData, "Status"),
                                      IsEvection = Utility.CheckXmlData(xmlData, "IsEvection"),
                                  };
                    context.AddToAccount(account);
                }
                else
                {
                    account.AccountName = Utility.CheckXmlData(xmlData, "AccountName");
                    account.Password = Utility.CheckXmlData(xmlData, "Password");
                    account.Type = Utility.CheckXmlData(xmlData, "Type");
                    account.Name = Utility.CheckXmlData(xmlData, "Name");
                    account.Status = Utility.CheckXmlData(xmlData, "Status");
                    account.IsEvection = Utility.CheckXmlData(xmlData, "IsEvection");
                }
                var result = context.SaveChanges();
                return result == 1 ? 0 : 1;
            }
            catch
            {
                throw new Exception("写入Account数据时出错！");
            }
        }
        private static int SetCertificate(System.Xml.XmlNode xmlData, orgEntities context)
        {
            try
            {
                var id = Utility.CheckXmlData(xmlData,"Guid");
                var certificate = context.Certificate.FirstOrDefault(cc => cc.Guid == id);
                if(null==certificate)
                {
                    certificate = new Certificate
                                      {
                        Guid = Utility.CheckXmlData(xmlData,"Guid"),
                        AccountName = Utility.CheckXmlData(xmlData,"AccountName"),
                        PublicKey = Utility.CheckXmlData(xmlData,"PublicKey"),
                        Type = Utility.CheckXmlData(xmlData,"Type"),
                        Name = Utility.CheckXmlData(xmlData,"Name"),
                        Status = Utility.CheckXmlData(xmlData,"Status")
                    };
                    context.AddToCertificate(certificate);
                }
                certificate.AccountName = Utility.CheckXmlData(xmlData,"AccountName");
                certificate.PublicKey = Utility.CheckXmlData(xmlData,"PublicKey");
                certificate.Type = Utility.CheckXmlData(xmlData,"Type");
                certificate.Name = Utility.CheckXmlData(xmlData,"Name");
                certificate.Status = Utility.CheckXmlData(xmlData,"Status");
                var result = context.SaveChanges();
                return result == 1 ? 0 : 1;
            }
            catch
            {
                throw new Exception("写入Certificate数据时出错！");
            }
        }
        #endregion
        #region\\transform
        public System.Xml.XmlNode TransformTaskData(OUDataInfo userInfo, System.Xml.XmlNode xmlParam, orgEntities context, BaseTaskDataSource baseInfo)
        {
            var datatype = XmlNodeManage.GetSubValue(xmlParam, "@DataType");
            switch (datatype.ToLower())
            {
                case "loginticket": return TransformLoginTicket(xmlParam, context, baseInfo);
                case "certticket": return TransformCertTicket(xmlParam, context, baseInfo);
                case "pageticket": return TransformPageTicket(xmlParam, context, baseInfo);
                default: throw new Exception("AuthenticationDS无法处理该" + datatype + "的数据");
            }
        }

        private static System.Xml.XmlNode TransformLoginTicket(System.Xml.XmlNode xmlParam, orgEntities context, BaseTaskDataSource baseInfo)
        {
            var userName = Utility.CheckXmlData(xmlParam,"//UserName");
            var password = Utility.CheckXmlData(xmlParam, "//Password");
            var time = Utility.CheckXmlData(xmlParam, "//EncryptTime");
            var ipAddress = Utility.CheckXmlData(xmlParam, "IPAddress");
            var acctEntity = context.Account.FirstOrDefault(cc => cc.AccountName.Equals(userName) && cc.Password.Equals(password));
            var result = XmlNodeManage.GetDocumentNode("0690f841-7773-445c-9f48-a7a0427686d5", "", "LoginTicket");
            var idNode = XmlNodeManage.CreateNode("UserID");
            if (string.IsNullOrEmpty(time) || !Utility.MatchTime(time, baseInfo.ConfigInfo.FormLoginTimeOut) || null == acctEntity ||
                acctEntity.Status.ToLower().Trim().Equals("disable"))
            {
                idNode.InnerText = string.Empty;
            }
            else
            {
                if (acctEntity.Type.ToLower().Trim() == "application")
                {
                    var item = context.Application.FirstOrDefault(cc => cc.Guid == acctEntity.Guid && cc.IPAddress == ipAddress);
                    var isValid = null == item ? false : true; 
                    if (isValid)
                        idNode.InnerText = Utility.Encode(acctEntity.Guid, password);
                    else
                        idNode.InnerText = string.Empty;
                }
                else
                    idNode.InnerText = Utility.Encode(acctEntity.Guid, password);
            }
            result.AppendChild(idNode);
            return result;
        }
        private static System.Xml.XmlNode TransformCertTicket(System.Xml.XmlNode xmlParam, orgEntities context, BaseTaskDataSource baseInfo)
        {
            var userName = Utility.CheckXmlData(xmlParam, "//UserName");
            var time = Utility.CheckXmlData(xmlParam, "//EncryptTime");
            var ipAddress = Utility.CheckXmlData(xmlParam, "IPAddress");
            //var acctEntity = context.Account.FirstOrDefault<Account>(cc => cc.Name.Equals(userName) && cc.Password.Equals(password));
            var result = XmlNodeManage.GetDocumentNode("0690f841-7773-445c-9f48-a7a0427686d5", "", "CertTicket");
            var idNode = XmlNodeManage.CreateNode("UserID");
            var certEntity = context.Certificate.FirstOrDefault(cc => cc.AccountName == userName);
            if (string.IsNullOrEmpty(time) || !Utility.MatchTime(time, baseInfo.ConfigInfo.FormLoginTimeOut) || null == certEntity ||
            certEntity.Status.ToLower().Trim().Equals("disable"))
            {
                idNode.InnerText = string.Empty;
            }
            else
            {
                var pk = certEntity.PublicKey.Replace("&lt;", "<").Replace("&gt;", ">");
                if (certEntity.Type.ToLower().Trim().Equals("application")) //应用软件还要验证IP地址
                {
                    //var item = context.Application.FirstOrDefault<Application>(cc => cc.Guid == certEntity.Guid && cc.IPAddress == ipAddress);
                    var item = context.Application.FirstOrDefault(cc => cc.Guid == certEntity.Guid);
                    var isValid = null == item ? false : true;
                    idNode.InnerText = isValid ? Utility.EncryptByPublicKey(pk, certEntity.Guid) : string.Empty;
                }
                else
                    idNode.InnerText = Utility.EncryptByPublicKey(pk, certEntity.Guid);
            }
            result.AppendChild(idNode);
            return result;
        }
        private static System.Xml.XmlNode TransformPageTicket(System.Xml.XmlNode xmlParam, orgEntities context, BaseTaskDataSource baseInfo)
        {
            var userName = Utility.CheckXmlData(xmlParam, "//UserName");
            var password = Utility.CheckXmlData(xmlParam, "//Password");
            var acctEntity = context.Account.FirstOrDefault(cc => cc.AccountName.Equals(userName) && cc.Password.Equals(password));
            var result = XmlNodeManage.GetDocumentNode("0690f841-7773-445c-9f48-a7a0427686d5", "", "PageTicket");
            var idNode = XmlNodeManage.CreateNode("UserID");
            if ( null == acctEntity || acctEntity.Status.ToLower().Trim().Equals("disable"))
            {
                idNode.InnerText = string.Empty;
            }
            else
            {
                idNode.InnerText = acctEntity.Guid;
            }
            result.AppendChild(idNode);
            return result;
        }
        #endregion
    }
}
